/****************************************************************/
/*																*/
/*  XmlToolBar.cpp												*/
/*																*/
/*  Implementation of the CXmlToolBar class.					*/
/*	The class can create ToolBar from XML file.					*/
/*																*/
/****************************************************************/

#include "stdafx.h"
#include "XmlToolBar.h"
#include "xmltoolbarview.h"

#include "..\\resource.h"

// CXmlToolBar

//Enables objects of CObject-derived classes to be created dynamically at run time
IMPLEMENT_DYNAMIC(CXmlToolBar, CToolBar)

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CXmlToolBar::CXmlToolBar()
{
	TBView =  new CXmlToolBarView;
}

// Clear tool tips text array

CXmlToolBar::~CXmlToolBar()
{
	m_asToolTips.clear();
}


BEGIN_MESSAGE_MAP(CXmlToolBar, CToolBar)
END_MESSAGE_MAP()

// CMyDynamicToolBar message handlers
// CToolBar::OnNotify is overriden event for responding to the TTN_NEEDTEXT message of the tool bar.

BOOL CXmlToolBar::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
      LPNMHDR pNMHDR = ((LPNMHDR)lParam);
      TOOLTIPTEXTW *pTTT=(TOOLTIPTEXTW *)pNMHDR;
      UINT t = TTN_NEEDTEXTW;
      if(pNMHDR->code == t) {
   
         UINT nID=pNMHDR->idFrom;
         if(!(pTTT->uFlags & TTF_IDISHWND))
         {
            if ((nID >= ID_MYTOOLBAR_BUTTON1) || (nID <= ID_MYTOOLBAR_BUTTONLAST))
               {
                  USES_CONVERSION;

				  UINT btn1 = ID_MYTOOLBAR_BUTTON1;

                  pTTT->lpszText = (LPWSTR)(LPCWSTR)(m_asToolTips[nID - btn1]); 
                  pTTT->hinst = NULL;
                  return TRUE;
               }
         }

    }
	return CToolBar::OnNotify(wParam, lParam, pResult);
}

// Inserts tool tips text consecutively

void CXmlToolBar::InsertToolTip(CString sToolTip)
{
	m_asToolTips.push_back(sToolTip);
}

// Retrieve Tool Tip text

CString CXmlToolBar::GetToolTip(UINT nID)
{
	UINT btn1 = ID_MYTOOLBAR_BUTTON1;
	return m_asToolTips[nID - btn1];
}

// function to load the xml file to trace into and call recursive function

CString CXmlToolBar::TraceXml(CString filename, CString attr, int id)
{
	CXmlElement *pElement;

	m_attr = attr;
	m_id = id;

	m_items.RemoveAll();
	
	//load the xml file for the toolbar button informatin
	if(m_xmldoc.SetXmlFile(filename))
	{
		pElement = this->m_xmldoc.GetRootElement();
		pElement = this->m_xmldoc.FindElement(pElement,_T("toolbar"));

		LoadtbButtonInfo(pElement);
		return _T("TRUE");
	}
	else
	{	
		return _T("FALSE");
	}
	
}
// Function to find the button names from xml file recursively

void CXmlToolBar::LoadtbButtonInfo(CXmlElement * pElement)
{
	// set the first child of the pElement to start searching toolbar items
	CXmlElement *pChild = m_xmldoc.GetFirstChild(pElement);
	CString name;

	//recursive loop to get the toolbar items and add in the array
	while (pChild != NULL)
	{
		name = pChild->GetValue(m_attr);

		if (pChild->m_ChildElements.GetCount()==0)
		{
			m_items.Add(name);
			m_id++;
			
		}
		else
			//recursive call
			LoadtbButtonInfo(pChild);
		

		pChild = m_xmldoc.GetNextSibling(pElement);

	}	// End of loop

}	

// function to draw bitmap to toolbar that holds the button images

BOOL CXmlToolBar::OnDrawToolBar()
{
	// toolbar button size initialization
	int tbb_X = 16;
	int tbb_Y = 16;
	this->SetButtonSize(tbb_X, tbb_Y);

	//destination device context for button image to be written
	CDC *dc = this->GetDC();
	
	CDC dcMem; 
	dcMem.CreateCompatibleDC(dc);

	// create bitmap to hold the button image
	HBITMAP hbitmap = CreateCompatibleBitmap(dc->m_hDC, 50*tbb_X, tbb_Y);
	CBitmap *bmp = CBitmap::FromHandle(hbitmap);
	CBitmap* pOldBitmap = dcMem.SelectObject( bmp );
	
	// Setting no. of tbButtons
	int tbButtons = this->m_id - 1025;

	//draw a filled rectangle with the default button color 
	CRect rect(0, 0, tbButtons*tbb_X, tbb_Y);
	FillRect(dcMem.m_hDC, &rect, (HBRUSH) (COLOR_BTNSHADOW));
	
	//divice context mapmode settings
	dcMem.SetMapMode(MM_TEXT);

	// if image path is not found in xml file then application exits
	if( !this->GetImgPath() || m_path.IsEmpty())
	{
		::AfxMessageBox(_T("Please specify image path in xml file"), MB_OKCANCEL, 0);
		exit(0);
	}

	CString tbbStr;
	CString tbbImgName;
	CString tbbImgPath = m_path;

	int i;
	for (i=0;i<tbButtons;i++)
	{
		tbbStr = this->m_items.GetAt(i);
		tbbImgName = tbbImgPath + tbbStr + _T(".bmp");
		
		if(!tbbStr.CompareNoCase(CONST_TOOLBAR_XML_SEPRAATOR_TAG)==0)
		{
			//paint the image dynamically from the image path on the toolbar view
			this->TBView->OnPaint(dc, &dcMem, tbbImgName, i*16, 0);
		}
		
		this->InsertToolTip(tbbStr);
		
	}

	// release device context
	dcMem.SelectObject(pOldBitmap); 
	dcMem.DeleteDC();
	pOldBitmap->DeleteObject();

	this->SetBitmap(hbitmap);

	//Add buttons for toolbar
	BOOL tbb = this->SetButtons(NULL,i);	
	if(!tbb)
		return false;
	else
		for(int j=0; j<i; j++) {
			tbbStr = this->m_items.GetAt(j);
						
			if(tbbStr.CompareNoCase(CONST_TOOLBAR_XML_SEPRAATOR_TAG)==0)
				//separator
				this->SetButtonInfo(j, 0, TBBS_SEPARATOR, 20);
			else
				//button
				this->SetButtonInfo(j, ID_MYTOOLBAR_BUTTON1 + j, TBBS_BUTTON | TBBS_AUTOSIZE, j);
		}	// end	create dynamic tool bar

		return true;

}

// function to set the toolbar button size

void CXmlToolBar::SetButtonSize(int cx, int cy)
{
	// set the button sizes - the sizes below are what we use for our app
    SIZE sz1;
    SIZE sz2;
    sz1.cx = cx; // default toolbar button width is 16
    sz1.cy = cy; // default toolbar button width is 15
    // msdn says to add this much to account for borders and such
    sz2.cx = sz1.cx + 7; 
    sz2.cy = sz1.cy + 6;

	this->SetSizes(sz2, sz1);
}

// Function to find the node in xml file with the image path

BOOL CXmlToolBar::GetImgPath()
{
	CXmlElement *pElement;

	m_attr = "imgpathentry";

	pElement = this->m_xmldoc.GetRootElement();
	pElement = this->m_xmldoc.FindElement(pElement, _T("imagepath"));
	
	if(pElement!=NULL)
	{
		this->LoadImgPathInfo(pElement);
		return true;
	}
	return false;
}

// function find the image path in the xml file

void CXmlToolBar::LoadImgPathInfo(CXmlElement * pElement)
{
	// set the first child of the pElement to start searching
	CXmlElement *pChild = m_xmldoc.GetFirstChild(pElement);
	
	CString name;
	int pathCnt=0;

	name = pChild->GetValue(m_attr);
	
	// recursive loop to retrieve the image path to store in
	while (pChild != NULL)
	{
		name = pChild->GetValue(m_attr);

		if (pChild->m_ChildElements.GetCount()==0 && pathCnt<=1)
		{
			// image path entry from xml file
			m_path = name;		
			// no. image path entry counted should be only 1
			pathCnt++;			

		}
		else
			//recursive call
			LoadtbButtonInfo(pChild);

		pChild = m_xmldoc.GetNextSibling(pElement);

	}	// End of loop


}